package com.example.controller;

import java.util.List;
import java.util.Map;
import java.util.HashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import com.example.dto.ApiResponse;
import com.example.dto.ExamRequest;
import com.example.dto.ExamStatisticsDTO;
import com.example.dto.MarkingSubmissionDTO;
import com.example.dto.SuspiciousBehaviorRecordRequest;
import com.example.entity.Exam;
import com.example.entity.ExamRecord;
import com.example.entity.User;
import com.example.entity.ExamAntiCheatingRecord;
import com.example.service.ExamService;
import com.example.service.UserService;
import com.example.service.ExamAntiCheatingService;

import jakarta.validation.Valid;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
@RequestMapping("/api/exams")
public class ExamController {

    private static final Logger log = LoggerFactory.getLogger(ExamController.class);

    @Autowired
    private ExamService examService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private ExamAntiCheatingService examAntiCheatingService;
    
    /**
     * 获取所有考试信息接口
     * 该接口用于获取系统中所有考试的信息，仅教师和管理员角色可访问。
     *
     * @return 返回包含所有考试信息的ResponseEntity对象
     */
    // 基本查询接口
    @GetMapping
    @PreAuthorize("hasAnyRole('TEACHER', 'ADMIN')")
    public ResponseEntity<List<Exam>> getAllExams() {
        return ResponseEntity.ok(examService.getAllExams());
    }
    
    /**
     * 获取当前教师的考试列表
     * 该接口用于获取当前登录教师用户的所有考试列表，通过用户ID查询对应的考试信息
     *
     * @return ResponseEntity 包含考试列表的响应实体
     */
    @GetMapping("/teacher")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<List<Exam>> getTeacherExams() {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.getTeacherExams(user.getId()));
    }
    
    /**
     * 获取当前学生的考试列表
     * 该接口用于获取当前登录学生的所有考试信息
     *
     * @return ResponseEntity封装了包含考试列表的响应体
     */
    @GetMapping("/student")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<List<Exam>> getStudentExams() {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.getStudentExams(user.getId()));
    }
    
    /**
     * 根据ID获取考试信息
     * 该接口用于通过考试ID获取考试的详细信息，仅教师、用户和管理员角色可访问。
     *
     * @param id 考试ID
     * @return 返回包含考试详细信息的ResponseEntity对象
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAnyRole('TEACHER', 'USER', 'ADMIN')")
    public ResponseEntity<Exam> getExamById(@PathVariable Long id) {
        return ResponseEntity.ok(examService.getExamById(id));
    }
    
    /**
     * 创建考试接口
     * 该接口用于教师角色创建新的考试，并返回创建结果。
     *
     * @param examRequest 考试请求对象，包含考试的详细信息
     * @return ResponseEntity对象，包含API响应和HTTP状态码
     */
    // 考试管理接口
    @PostMapping
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> createExam(@Valid @RequestBody ExamRequest examRequest) {
        User user = getCurrentUser();
        return new ResponseEntity<>(examService.createExam(examRequest, user.getId()), HttpStatus.CREATED);
    }
    
    /**
     * 更新考试信息接口
     * 根据提供的考试ID和请求体中的考试信息更新考试数据，只允许教师角色操作。
     *
     * @param id 考试的唯一标识符，用于定位要更新的考试记录
     * @param examRequest 包含更新后的考试信息的请求体
     * @return 返回包含操作结果的API响应实体
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> updateExam(@PathVariable Long id, @Valid @RequestBody ExamRequest examRequest) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.updateExam(id, examRequest, user.getId()));
    }
    
    /**
     * 保存考试草稿
     * 教师通过此接口可以保存考试的草稿，草稿将关联到指定的考试ID。
     *
     * @param id 考试的唯一标识符
     * @param examRequest 考试请求对象，包含考试的相关信息
     * @return 返回一个包含操作结果的响应实体
     */
    @PostMapping("/{id}/draft")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> saveDraft(@PathVariable Long id, @Valid @RequestBody ExamRequest examRequest) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.saveDraft(id, examRequest, user.getId()));
    }
    
    /**
     * 删除考试接口
     * 根据提供的考试ID删除对应的考试记录，只有教师角色可以调用此接口
     *
     * @param id 要删除的考试的ID
     * @return 返回操作结果的响应实体
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> deleteExam(@PathVariable Long id) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.deleteExam(id, user.getId()));
    }
    
    /**
     * 发布考试
     * 教师通过此接口发布指定ID的考试
     *
     * @param id 考试ID
     * @return 返回操作结果的响应实体
     */
    // 考试状态管理
    @PostMapping("/{id}/publish")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> publishExam(@PathVariable Long id) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.publishExam(id, user.getId()));
    }
    
    /**
     * 启动考试
     * 教师角色通过此接口启动指定ID的考试
     *
     * @param id 考试ID
     * @return 返回操作结果的API响应
     */
    @PostMapping("/{id}/start")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> startExam(@PathVariable Long id) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.startExam(id, user.getId()));
    }
    
    /**
     * 结束考试接口
     * 根据提供的考试ID结束对应的考试，并返回操作结果
     *
     * @param id 考试ID
     * @return ResponseEntity对象，包含操作结果的ApiResponse
     * @ 如果当前用户没有TEACHER角色，则抛出该异常
     */
    @PostMapping("/{id}/end")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> endExam(@PathVariable Long id) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.endExam(id, user.getId()));
    }
    
    /**
     * 添加题目到指定考试
     * 该接口用于教师将一组题目添加到指定的考试中
     *
     * @param id       考试ID
     * @param questionIds 要添加的题目ID列表
     * @return 返回操作结果的API响应
     */
    // 题目管理
    @PostMapping("/{id}/questions")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> addQuestions(@PathVariable Long id, @RequestBody List<Long> questionIds) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.addQuestions(id, questionIds, user.getId()));
    }
    
    /**
     * 删除指定考试中的题目
     * 该接口用于教师角色删除指定考试ID下的一组题目ID，删除操作由当前登录的教师用户发起。
     *
     * @param id 考试的唯一标识符
     * @param questionIds 需要删除的题目ID列表
     * @return 返回包含操作结果的API响应实体
     */
    @DeleteMapping("/{id}/questions")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> removeQuestions(@PathVariable Long id, @RequestBody List<Long> questionIds) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.removeQuestions(id, questionIds, user.getId()));
    }
    
    /**
     * 生成随机问题
     * 教师角色通过该接口可以为学生生成随机问题
     *
     * @param id     路径参数，表示学生的ID
     * @param request 请求体，包含生成问题所需的请求信息，如问题数量等
     * @return 返回一个包含响应数据的ResponseEntity对象
     */
    @PostMapping("/{id}/random-questions")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> generateRandomQuestions(@PathVariable Long id, @RequestBody ExamRequest request) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.generateRandomQuestions(id, request, user.getId()));
    }
    
    /**
     * 学生开始考试接口
     * 该接口用于学生开始某个班级的考试，需要用户角色权限
     *
     * @param id 学生ID，路径参数
     * @param classId 班级ID，请求参数，必须提供
     * @return 返回操作结果的响应实体
     */
    // 学生考试接口
    @PostMapping("/{id}/start-exam")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<?>> startExamByStudent(
            @PathVariable Long id,
            @RequestParam(required = true) Long classId) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.startExamByStudent(id, user.getId(), classId));
    }
    
    /**
     * 提交考试答案
     * 用户通过该接口提交考试答案，系统会对答案进行处理并返回结果
     *
     * @param id 考试ID，用于标识要提交的考试
     * @param answers 用户提交的答案，JSON字符串格式
     * @return 返回一个包含操作结果的ResponseEntity对象
     *  如果用户没有'USER'角色，则抛出该异常
     */
    @PostMapping("/{id}/submit")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<?>> submitExam(@PathVariable Long id, @RequestBody String answers) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.submitExam(id, user.getId(), answers));
    }

    /**
     * 保存问题答案
     * 根据考试ID和问题ID保存用户提交的问题答案
     *
     * @param examId 考试ID
     * @param questionId 问题ID
     * @param answer 用户提交的问题答案
     * @return 返回操作结果的响应实体
     */
    @PostMapping("/{examId}/questions/{questionId}/answer")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<?>> saveQuestionAnswer(
            @PathVariable Long examId,
            @PathVariable Long questionId,
            @RequestBody String answer) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.saveQuestionAnswer(examId, questionId, user.getId(), answer));
    }
    
    /**
     * 获取当前学生考试的剩余时间
     * @param examId 考试ID
     * @return ApiResponse 包含剩余时间的响应
     */
    @GetMapping("/{examId}/remaining-time")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<?>> getRemainingTime(@PathVariable Long examId) {
        User user = getCurrentUser();
        System.out.println("Remaining time: " + examService.getRemainingTime(examId, user.getId()));
        return ResponseEntity.ok(examService.getRemainingTime(examId, user.getId()));
    }
    
    /**
     * 获取指定考试的记录
     * 根据考试ID获取该考试的所有记录，仅教师角色可访问
     *
     * @param id 考试的唯一标识符
     * @return 包含考试记录的响应实体
     */
    // 考试记录和批改
    @GetMapping("/{id}/records")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<List<ExamRecord>> getExamRecords(@PathVariable Long id) {
        return ResponseEntity.ok(examService.getExamRecords(id));
    }
    
    /**
     * 开始批改指定记录的考试
     * 该接口允许教师用户开始批改指定记录ID的考试，返回操作结果
     *
     * @param recordId 要批改的考试记录ID
     * @return ResponseEntity对象，包含操作结果的ApiResponse
     *  如果当前用户没有教师角色，则抛出该异常
     */
    @PostMapping("/records/{recordId}/start-marking")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> startMarking(@PathVariable Long recordId) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.startMarking(recordId, user.getId()));
    }
    
    /**
     * 提交作业评分
     * 教师通过该接口提交对学生作业的评分
     *
     * @param recordId 作业记录ID
     * @param submission 提交的评分信息
     * @return 返回操作结果的API响应
     */
    @PostMapping("/records/{recordId}/submit-marking")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> submitMarking(@PathVariable Long recordId,
                                                      @RequestBody MarkingSubmissionDTO submission) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.submitMarking(recordId, submission, user.getId()));
    }
    
    /**
     * 获取考试统计信息接口
     * 该接口用于教师角色获取指定考试的统计信息
     *
     * @param examId 考试ID
     * @return ApiResponse<ExamStatisticsDTO> 返回包含考试统计信息的ApiResponse对象
     */
    // 统计和分析
    @GetMapping("/{id}/statistics")
    @PreAuthorize("hasRole('TEACHER')")
    public ApiResponse<ExamStatisticsDTO> getExamStatistics(@PathVariable("id") Long examId) {
        return ApiResponse.success("获取考试统计信息成功", examService.getExamStatistics(examId));
    }
    
    /**
     * 获取班级考试统计信息
     * 根据提供的教师和班级ID，获取对应班级的考试统计信息
     *
     * @param id 教师ID
     * @param classId 班级ID
     * @return 包含班级考试统计信息的ResponseEntity对象
     */
    @GetMapping("/{id}/class/{classId}/statistics")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<Map<String, Object>> getClassExamStatistics(
            @PathVariable Long id,
            @PathVariable Long classId) {
        return ResponseEntity.ok(examService.getClassExamStatistics(id, classId));
    }
    
    /**
     * 获取指定考试的疑似作弊行为
     * 根据考试ID获取该考试中所有疑似作弊的行为列表
     *
     * @param id 考试ID
     * @return 返回一个包含疑似作弊行为的列表，每个行为以Map形式表示
     */
    // 作弊检测
    @GetMapping("/{id}/suspicious-actions")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<List<Map<String, Object>>> getSuspiciousActions(@PathVariable Long id) {
        return ResponseEntity.ok(examService.getSuspiciousActions(id));
    }
    
    /**
     * 获取学生的可疑行为
     * 根据提供的考试ID和学生ID，获取该学生在该考试中的可疑行为列表
     *
     * @param id 考试ID
     * @param studentId 学生ID
     * @return 返回包含可疑行为列表的ResponseEntity对象
     */
    @GetMapping("/{id}/student/{studentId}/suspicious-actions")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<List<Map<String, Object>>> getStudentSuspiciousActions(
            @PathVariable Long id,
            @PathVariable Long studentId) {
        return ResponseEntity.ok(examService.getStudentSuspiciousActions(id, studentId));
    }
    
    /**
     * 获取考试的详细防作弊记录
     * 获取考试中所有详细的可疑行为记录（来自专门的防作弊记录表）
     *
     * @param id 考试ID
     * @return 返回详细的防作弊记录列表
     */
    @GetMapping("/{id}/detailed-anti-cheating-records")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getDetailedAntiCheatingRecords(@PathVariable Long id) {
        try {
            List<ExamAntiCheatingRecord> records = examAntiCheatingService.getExamSuspiciousRecords(id);
            return ResponseEntity.ok(ApiResponse.success("获取详细防作弊记录成功", records));
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("获取详细防作弊记录失败：" + e.getMessage()));
        }
    }
    
    /**
     * 获取学生的详细防作弊记录
     * 获取特定学生在考试中的详细可疑行为记录
     *
     * @param id 考试ID
     * @param studentId 学生ID
     * @return 返回学生的详细防作弊记录列表
     */
    @GetMapping("/{id}/student/{studentId}/detailed-anti-cheating-records")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getStudentDetailedAntiCheatingRecords(
            @PathVariable Long id,
            @PathVariable Long studentId) {
        try {
            List<ExamAntiCheatingRecord> records = examAntiCheatingService.getStudentSuspiciousRecords(id, studentId);
            return ResponseEntity.ok(ApiResponse.success("获取学生详细防作弊记录成功", records));
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("获取学生详细防作弊记录失败：" + e.getMessage()));
        }
    }
    
    /**
     * 获取考试防作弊统计信息
     * 获取考试的详细防作弊统计数据
     *
     * @param id 考试ID
     * @return 返回防作弊统计信息
     */
    @GetMapping("/{id}/anti-cheating-statistics")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getAntiCheatingStatistics(@PathVariable Long id) {
        try {
            Map<String, Object> statistics = examAntiCheatingService.getExamSuspiciousStatistics(id);
            return ResponseEntity.ok(ApiResponse.success("获取防作弊统计信息成功", statistics));
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("获取防作弊统计信息失败：" + e.getMessage()));
        }
    }
    
    /**
     * 获取学生防作弊统计信息
     * 获取特定学生在考试中的防作弊统计数据
     *
     * @param id 考试ID
     * @param studentId 学生ID
     * @return 返回学生的防作弊统计信息
     */
    @GetMapping("/{id}/student/{studentId}/anti-cheating-statistics")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getStudentAntiCheatingStatistics(
            @PathVariable Long id,
            @PathVariable Long studentId) {
        try {
            Map<String, Object> statistics = examAntiCheatingService.getStudentSuspiciousStatistics(id, studentId);
            return ResponseEntity.ok(ApiResponse.success("获取学生防作弊统计信息成功", statistics));
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("获取学生防作弊统计信息失败：" + e.getMessage()));
        }
    }
    
    /**
     * 记录可疑行为（实时记录）
     * 用于在考试过程中实时记录学生的可疑行为
     *
     * @param id 考试ID
     * @param request 可疑行为记录请求
     * @return 返回记录结果
     */
    @PostMapping("/{id}/record-suspicious-behavior")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<?>> recordSuspiciousBehavior(
            @PathVariable Long id,
            @RequestBody SuspiciousBehaviorRecordRequest request) {
        try {
            User user = getCurrentUser();
            
            // 验证请求参数
            if (request.getBehaviorType() == null || request.getBehaviorType().trim().isEmpty()) {
                return ResponseEntity.ok(ApiResponse.error("行为类型不能为空"));
            }
            
            // 调用服务记录可疑行为
            ApiResponse<?> result = examService.recordSuspiciousAction(
                    id, user.getId(), request.getBehaviorType(), request.getDetails());
            
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("记录可疑行为失败：" + e.getMessage()));
        }
    }
    
    /**
     * 获取学生的考试记录详情
     * 该接口用于学生查看自己的考试记录和批改结果
     *
     * @param examId 考试ID
     * @return 返回包含考试记录详情的响应实体
     */
    @GetMapping("/{examId}/my-record")
    @PreAuthorize("hasRole('USER') or hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getMyExamRecord(@PathVariable Long examId) {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.getStudentExamRecordDetail(examId, user.getId()));
    }
    
    /**
     * 教师获取指定学生的考试记录详情
     * 该接口用于教师查看指定学生在特定考试中的记录和批改结果
     *
     * @param examId  考试ID
     * @param studentId 学生ID
     * @return 返回包含考试记录详情的响应实体
     */
    @GetMapping("/{examId}/student-record")
    @PreAuthorize("hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getStudentExamRecordForTeacher(
            @PathVariable Long examId,
            @RequestParam Long studentId) {
        return ResponseEntity.ok(examService.getStudentExamRecordDetail(examId, studentId));
    }

    /**
     * 获取学生的所有考试记录列表
     * 该接口用于学生查看自己参加过的所有考试记录
     *
     * @return 返回包含所有考试记录的响应实体
     */
    @GetMapping("/my-records")
    @PreAuthorize("hasRole('USER') or hasRole('TEACHER')")
    public ResponseEntity<ApiResponse<?>> getMyExamRecords() {
        User user = getCurrentUser();
        return ResponseEntity.ok(examService.getStudentExamRecordList(user.getId()));
    }
    
    /**
     * 获取当前用户信息
     *
     * @return 当前用户信息
     */
    private User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        return userService.getUserByUsername(username);
    }
} 